iT邦幫忙

2022 iThome 鐵人賽

DAY 4
1
Software Development

C# ASP.NET MVC實作: 30天打造屬於你的網站應用程式系列 第 4

(DAY 4)C# ASP .NET MVC實作: 30天打造屬於你的網站應用程式-新增View 與 資料傳遞(一): ViewData、ViewBag、TempData

  • 分享至 

  • xImage
  •  

今天主要來講如何新增View檢視頁面,以及資料傳遞的一些作法。
延續前一天的最後講到ActionResult的範例:

        // GET: Demo
        public ActionResult Index()
        {
            return View();
        }

當我們將程式執行起來並進入URL https://localhost:44349/Demo/Index 的時候,會看到畫面如下的錯誤,表示找不到動作方法相對應的View畫面。當動作方法回傳的是ViewResult時,我們其實應該要為它新增一個檢視頁面。

● 新增檢視

新增檢視頁面的步驟如下:

  1. return View();View()上方按下滑鼠右鍵,點選「新增檢視」

  2. 選擇「MVC5檢視」並點擊「加入」

  3. 「檢視名稱」照預設會與動作方法名稱相符,範本維持預設選擇「Empty(沒有模型)」,預設勾選為「使用版面配置頁」,這邊我們都先不修改,直接按下「加入」即會自動生成View檔案。

  4. 產生後畫面如下,可以發現檔案是生成在「Views」 → 「Demo」資料夾底下,自動與控制器名稱對應好了呢!

生成的View是屬於.cshtml檔,顧名思義它可以讓我們在裡面同時撰寫C#與HTML的語法,但在使用C#語法時,必須在前面先加上@符號,如果有包含整句程式碼則使用大括號{ }將程式碼區塊包起來,這個稱為「Razor語法」;另外如果在C#語法後還要接HTML格式則要空一格或換行。比如我們隨意新增程式碼如下:

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<div>
    今年是:@DateTime.Now.Year 年
</div>

直接在View程式碼上按下滑鼠右鍵,點擊「在瀏覽器中檢視」可以看到顯示結果如下圖:

另外因為在新增View的時候有勾選「使用版面配置頁」,所以看到一樣會套用預設Layout版面。

● 資料傳遞:ViewData

在做少量的資料傳遞時,我們可以透過ViewData、ViewBag、TempData三種物件來存取傳到View。
ViewData的存取是透過Key/Value的形式,Key必須是唯一,寫法是 ViewData["Key"] = Value;
例如在 DemoController底下Index()方法,新增Code如下:

        // GET: Demo
        public ActionResult Index()
        {
            ViewData["Name"] = "陳小強";
            return View();
        }

然後在對應的View頁面修改成如下方Code:

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<div>
    今年是:@DateTime.Now.Year 年
    <br />
    我的名字是: @ViewData["Name"]
</div>

顯示結果如下圖:

● 資料傳遞:ViewBag

ViewBag的使用方式和ViewData類似,差別在於ViewBag是使用動態(dynamic)型別,可以省去手動轉型的麻煩,但相對ViewData執行速度較慢。(但少量資料我們其實感受不到)
寫法是 ViewBag.屬性 = 屬性值;
我們可以將ViewData的範例改寫如下:

        // GET: Demo
        public ActionResult Index()
        {
            //ViewData["Name"] = "陳小強";
            ViewBag.Name = "陳小強";
            return View();
        }

View


@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<div>
    今年是:@DateTime.Now.Year 年
    <br />
    我的名字是: @ViewBag.Name
</div>

顯示結果和ViewData一樣:

● 資料傳遞:TempData

TempData 和 ViewData 寫法很像,都是透過Key/Value的形式存取資料,
寫法是:TempData["Key"] = Value;
但差別在於ViewData的生命週期只有一次Request(請求),請求完就會被刪除了。而TempData會暫時存在Session中,最多可以經導向一次,在二次導向頁面時才會被清除。
範例如下:

        // GET: Demo
        public ActionResult Index()
        {
            //ViewData["Name"] = "陳小強";
            //ViewBag.Name = "陳小強";
            TempData["Name"] = "陳小強";
            return View();
        }

View

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<div>
    今年是:@DateTime.Now.Year 年
    <br />
    我的名字是: @TempData["Name"]
</div>

顯示結果和ViewData一樣:

接著我們示範一下TempData經由一次導向後仍可傳遞的範例,並且看看是否ViewBag和ViewData無法存活到導向頁面。
我們改寫一下Index()的方法內容,並建立一個新的動作方法叫ShowTempData()。流程是當呼叫Index()後,會導向到ShowTempData()這個動作與顯示對應的View頁面,Code如下:

        // GET: Demo
        public ActionResult Index()
        {
            TempData["Name"] = "陳小強";
            ViewData["Name"] = "陳小強";
            ViewBag.Name = "陳小強";
            return RedirectToAction("ShowTempData");
        }

        public ActionResult ShowTempData()
        {
            return View();
        }

新增ShowTempData()方法的View頁面如下:


@{
    ViewBag.Title = "ShowTempData";
}

<h2>ShowTempData</h2>

<div>
    [使用TempData傳遞]
    我的名字是: @TempData["Name"]
    <br />
    [使用ViewData傳遞]
    我的名字是: @ViewData["Name"]
    <br />
    [使用ViewBag傳遞]
    我的名字是: @ViewBag.Name
</div>

當執行網址~Demo/Index 時,發現網址會導向到~Demo/ShowTempData,顯示結果如下:

由此可見確實只有TempData能夠成功被傳遞~

● ViewData vs ViewBag 轉型問題

上面提到ViewData和ViewBag的其中一個差異在於手動轉型的麻煩,我們用一個範例說明:

  1. 首先在DemoController底下再新增一個ShowMembers()方法
        public ActionResult ShowMembers()
        {
            return View();
        }
  1. 接著新增ShowMembers()的View,一樣使用預設的條件建立即可,建立後View Code如下:

@{
    ViewBag.Title = "ShowMembers";
}

<h2>ShowMembers</h2>
  1. 接著在Models資料夾底下新增一個類別名為Member,並簡單新增幾個屬性,Code如下:
    public class Member
    {
        //新增屬性可使用快捷鍵prop產生
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
  1. ShowMembers()方法新增幾行Code,用以建立幾個Member物件,並將這些物件加入List集合內,最後讓ViewData攜帶此List物件傳遞,Code如下:
        public ActionResult ShowMembers()
        {
            var memberA = new Member() { Id = 1, Name = "Alex", Age = 12 };
            var memberB = new Member() { Id = 2, Name = "Ben", Age = 34 };
            var memberC = new Member() { Id = 3, Name = "Carol", Age = 56 };
            var memberList = new List<Member>() { memberA, memberB, memberC };
            ViewData["Members"] = memberList;
            return View();
        }

※這邊可以發現ViewData不只能傳遞簡單型別資料,也能傳遞物件哦!
5. 在ShowMembers()的View修改成以下Code:

@using MyFirstWebApp.Models
@{
    ViewBag.Title = "ShowMembers";
}

<h2>ShowMembers</h2>

<div>
    @{
        foreach (var member in ViewData["Members"] as List<Member>)
        {
            <label>會員編號:</label> @member.Id
            <br />
            <label>會員姓名:</label> @member.Name
            <br />
            <label>年齡:</label> @member.Age
            <hr />
        }
    }
</div>

這邊利用foreach迴圈將ViewData["Members"]傳遞的List<Member>物件內資料全部顯示出來,並且可以發現這裡必須使用 as 關鍵字來指定ViewData["Members"]的型別。
另外,因為Member類別是在Models資料夾中,所以必須在上面引用該資料夾才能成功指定型別。


6. 在ShowMembers的View頁面按滑鼠右鍵,點擊「在瀏覽器中檢視」,顯示畫面如下圖:

7. 接著將ViewData改寫成ViewBag的方式,請參考下方Code:

DemoController:

        public ActionResult ShowMembers()
        {
            var memberA = new Member() { Id = 1, Name = "Alex", Age = 12 };
            var memberB = new Member() { Id = 2, Name = "Ben", Age = 34 };
            var memberC = new Member() { Id = 3, Name = "Carol", Age = 56 };
            var memberList = new List<Member>() { memberA, memberB, memberC };
            //ViewData["Members"] = memberList;
            ViewBag.Members = memberList;
            return View();
        }

View:


@{
    ViewBag.Title = "ShowMembers";
}

<h2>ShowMembers</h2>

<div>
    @{
        foreach (var member in ViewBag.Members)
        {
            <label>會員編號:</label> @member.Id
            <br />
            <label>會員姓名:</label> @member.Name
            <br />
            <label>年齡:</label> @member.Age
            <hr />
        }
    }
</div>

從View頁面的Code可以發現,在foreach迴圈的地方不需要指定ViewBag.Members的型別也能成功執行,當然因此不需要引用Models資料夾裡的Member類別了。比較起來是否覺得ViewBag寫法簡略一點呢?

● 小結

今天介紹了如何新增View,以及幾種資料傳遞的方式。在寫View的程式碼時會常用到許多HTML標籤的語法,但因為主題重點不是在說明HTML,所以就不一一解釋每行Code了。明天我們繼續講關於資料傳遞的其他模式,See U Tomorrow~~

※小弟不才,在軟體的世界還只是個小菜雞,如果內容有任何謬誤或問題,還請各位大神前輩們多多批評指教~歡迎下方留言討論^^


上一篇
(DAY 3)C# ASP .NET MVC實作: 30天打造屬於你的網站應用程式-新增Controller
下一篇
(DAY 5)C# ASP .NET MVC實作: 30天打造屬於你的網站應用程式-資料傳遞(二):物件Model
系列文
C# ASP.NET MVC實作: 30天打造屬於你的網站應用程式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言